/*
    This file is part of qmessages.
    Copyright (C) 2010  Jason Newton <nevion@gmail.com>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "QMessage.h"
#include <cassert>
#include <QDebug>

namespace qmsgio{

std::unordered_map<QMessage::tag_t, QMessage::message_ctor_t> QMessage::tag2Ctor;
std::unordered_map<std::string, QMessage::tag_t> QMessage::type2Tag;

void QMessage::register_message(const tag_t &tag, const std::type_info &class_t, const message_ctor_t &ctor){
    tag2Ctor[tag] = ctor;
    type2Tag[class_t.name()] = tag;
}

int QMessage::minMessageSize(){
    return sizeof(tag_t);
}

int QMessage::fixedSize(){
    return 0;
}

bool QMessage::parseFixed(QDataStream &stream){
    return true;
}

int QMessage::variableSize(){
    return 0;
}

bool QMessage::parseVariable(QDataStream &stream){
    return true;
}

bool QMessage::serialize(QDataStream &stream){
    serializeFixed(stream);
    serializeVariable(stream);
    return true;
}

bool QMessage::serializeFixed(QDataStream &stream){
    auto type = type2Tag.find(typeid(*this).name());
    //BOOST_VERIFY(type != type2Tag.end());
    stream<<type->second;
    return true;
}

bool QMessage::serializeVariable(QDataStream &stream){
    return true;
}

bool QMessage::deserialize(QDataStream &stream){
    parseFixed(stream);
    parseVariable(stream);
    return true;
}

std::unique_ptr<QMessage> QMessage::parseMessageHeader(QDataStream &stream){

    tag_t type;
    stream>>type;
    auto ctor = tag2Ctor.find(type);
    if(ctor != tag2Ctor.end()){
        return std::unique_ptr<QMessage>((ctor->second)());
    }else{
        qWarning()<<"Unhandled message type:"<<type;
        return std::unique_ptr<QMessage>(new QMessage());
    }
    return std::unique_ptr<QMessage>(0);
}

}
